package thread3;

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * 对同一个数字，两个线程，分别+1，-1，交替执行5次
 */
public class Customer {

    static class ShareData {
        private int number = 0;
        private final Lock lock = new ReentrantLock();
        private final Condition condition = lock.newCondition();

        public void increment() {
            try {
                lock.lock();
                // 首先判断是否需要生产
                while (number != 0) {
                    // 等待，不能生产
                    condition.await();
                }

                // 生产
                number++;
                System.out.println(Thread.currentThread().getName() + '\t' + number);

                // 通知唤醒
                condition.signalAll();
            } catch (InterruptedException e) {
                e.printStackTrace();
            } finally {
                lock.unlock();
            }
        }

        public void decrement() {
            try {
                lock.lock();
                // 首先判断是否需要生产
                while (number == 0) {
                    // 等待，不能生产
                    condition.await();
                }

                // 生产
                number--;
                System.out.println(Thread.currentThread().getName() + '\t' + number);

                // 通知唤醒
                condition.signalAll();
            } catch (InterruptedException e) {
                e.printStackTrace();
            } finally {
                lock.unlock();
            }
        }
    }


    public static void main(String[] args) {
        ShareData shareData = new ShareData();
        new Thread(() -> {
            for (int i = 0; i < 5; i++) {
                shareData.increment();
            }
        }, "a").start();

        new Thread(() -> {
            for (int i = 0; i < 5; i++) {
                shareData.decrement();
            }
        }, "b").start();
    }

    /*
    sychronized和Lock有什么区别？用Lock有什么好处？请举例~
    使用方式：
    synchronized (new Object()) {}
    new ReentrantLock();
    1、sychronized是一个关键字，Lock是jdk1.5以后提出的一个类
    2、sychronized不用手动释放，Lock需要unlock，而且最好是在finally里面执行
    3、sychronized不能中断，除非抛异常或者运行完成，Lock可以中断（
        设置超时方法：tryLock(long timeout,TimeUnit unit),
        lockInterruptibly()代码块中，调用interrupt()方法可以中断）
    4、sychronized默认非公平锁，Lock默认也是非公平锁，但是可以设置为公平锁
    5、ReentrantLock可以用来实现分组唤醒需要唤醒的线程们，可以精确唤醒，而不是像sychronized要么随机唤醒一个线程要么唤醒全部线程
     */
}
